from enum import Enum
from datetime import datetime
from typing import List, Optional, Tuple
from uuid import UUID, uuid4

from sqlalchemy import JSON, Column, DateTime, String, Text, func, text, update
from sqlmodel import Field, delete, select

from bisheng.database.base import session_getter
from bisheng.database.models.base import SQLModelSerializable


class LevelEnum(Enum):
    def __init__(self, level_name, num):
        self.level_name = level_name
        self.num = num

    EASY = ("极小", 1)
    MEDIUM = ("中等", 2)
    HARD = ("严重", 3)


class MetroFaultBase(SQLModelSerializable):
    id: UUID = Field(nullable=False, primary_key=True, description='唯一ID')
    report_order_code: str = Field(index=True, description='故障单编号')
    line: str = Field(index=False, default='', description='故障发生线路')
    equipment_id: str = Field(sa_column=Column(String(length=64), default=''), description='故障设备编号')
    equipment_name: str = Field(sa_column=Column(String(length=255), default=''), description='故障设备名称')
    fault_phenomenon: Optional[str] = Field(sa_column=Column(Text), description='故障现象')
    occurrence_time: Optional[datetime] = Field(
        sa_column=Column(DateTime, nullable=False, server_default=text('CURRENT_TIMESTAMP')),
        description='故障发生时间')
    fix_time: Optional[datetime] = Field(sa_column=Column(DateTime, nullable=True), description='故障修复时间')
    impact_operation: Optional[int] = Field(index=False, default=0, description='是否影响行车')
    impact_operation_time: Optional[str] = Field(index=False, default='', description='影响行车的时间')
    impact_service_time: Optional[str] = Field(index=False, default='', description='服务影响的时长')
    safety_impact_level: Optional[str] = Field(index=False, default='不影响', description='安全影响程度')
    env_impact_level: Optional[str] = Field(index=False, default='不影响', description='环境影响程度')
    incidence: Optional[str] = Field(index=False, default='部件本体/设备本体', description='影响范围')
    report: Optional[str] = Field(sa_column=Column(Text), description='故障报告')
    create_time: Optional[datetime] = Field(
        sa_column=Column(DateTime, nullable=False, server_default=text('CURRENT_TIMESTAMP')))
    update_time: Optional[datetime] = Field(
        sa_column=Column(DateTime,
                         nullable=False,
                         index=True,
                         server_default=text('CURRENT_TIMESTAMP'),
                         onupdate=text('CURRENT_TIMESTAMP')))


class MetroFault(MetroFaultBase, table=True):
    id: UUID = Field(default_factory=uuid4, primary_key=True, unique=True)


class MetroFaultDao(MetroFault):
    @classmethod
    def get_metro_fault_by_id(cls, id):
        """根据主键id获取地铁故障"""
        with session_getter() as session:
            statement = select(MetroFault).where(MetroFault.id == id)
            return session.exec(statement).first()

    @classmethod
    def get_metro_fault_by_report_order_code(cls, report_order_code):
        """根据故障单编号获取地铁故障"""
        with session_getter() as session:
            statement = select(MetroFault).where(MetroFault.report_order_code == report_order_code)
            return session.exec(statement).first()

    @classmethod
    def create_metro_fault(cls, metro_fault):
        with session_getter() as session:
            session.add(metro_fault)  # 添加到会话
            session.commit()  # 提交事务
            session.refresh(metro_fault)  # 刷新
            return metro_fault  # 返回创建的记录

    @classmethod
    def filter_metro_fault(cls, data):
        """根据条件过滤地铁故障记录"""
        with session_getter() as session:
            query = select(MetroFault)

            # 根据 equipment_id 过滤
            if 'equipment_id' in data and data['equipment_id']:
                query = query.where(MetroFault.equipment_id == data['equipment_id'])

            # 根据 safety_impact_level 过滤
            if 'safety_impact_level' in data and data['safety_impact_level']:
                query = query.where(MetroFault.safety_impact_level == data['safety_impact_level'])

            # 根据 env_impact_level 过滤
            if 'env_impact_level' in data and data['env_impact_level']:
                query = query.where(MetroFault.env_impact_level == data['env_impact_level'])

            # 根据 incidence 过滤
            if 'incidence' in data and data['incidence']:
                query = query.where(MetroFault.incidence == data['incidence'])

            # 根据 occurrence_time 时间范围过滤
            if 'start_time' in data and data['start_time']:
                if isinstance(data['start_time'], str):
                    start_time = datetime.fromisoformat(data['start_time'])
                elif isinstance(data['start_time'], datetime):
                    start_time = data['start_time']
                else:
                    raise ValueError("Invalid start_time format")
                query = query.where(MetroFault.occurrence_time >= start_time)

            if 'end_time' in data and data['end_time']:
                if isinstance(data['end_time'], str):
                    end_time = datetime.fromisoformat(data['end_time'])
                elif isinstance(data['end_time'], datetime):
                    end_time = data['end_time']
                else:
                    raise ValueError("Invalid end_time format")

                query = query.where(MetroFault.occurrence_time <= end_time)

            # 执行查询并返回结果
            return session.exec(query).all()

    @staticmethod
    def update_metro_fault(new_metro_fault):
        """更新地铁故障记录"""
        with session_getter() as session:
            # 查询要更新的记录
            stmt = select(MetroFault).where(MetroFault.id == new_metro_fault.id)
            result = session.execute(stmt)
            metro_fault = result.scalar_one_or_none()

            if not metro_fault:
                raise ValueError(f"No MetroFault found with id {new_metro_fault.report_order_code}")

            # 只更新非空值
            for key, value in new_metro_fault.dict(exclude_unset=True).items():
                if value is not None and hasattr(metro_fault, key):
                    setattr(metro_fault, key, value)

            session.commit()  # 提交事务
            session.refresh(metro_fault)  # 刷新对象
            return metro_fault  # 返回更新后的记录


class ConfigBase(SQLModelSerializable):
    id: UUID = Field(nullable=False, primary_key=True, description='唯一ID')
    key: str = Field(index=True, description='配置key')
    value: str = Field(index=False, description='配置value')
    remark: str = Field(index=False, description='备注')
    create_time: Optional[datetime] = Field(
        sa_column=Column(DateTime, nullable=False, server_default=text('CURRENT_TIMESTAMP')))
    update_time: Optional[datetime] = Field(
        sa_column=Column(DateTime,
                         nullable=False,
                         index=True,
                         server_default=text('CURRENT_TIMESTAMP'),
                         onupdate=text('CURRENT_TIMESTAMP')))


class MetroConfig(ConfigBase, table=True):
    id: UUID = Field(default_factory=uuid4, primary_key=True, unique=True)

    @classmethod
    def get_default_configs(cls) -> List['MetroConfig']:
        """
        返回默认配置列表
        """
        return [
            cls(key="use_model_url", value="http://172.16.100.156:7860/api/v2/assistant/chat/completions",
                remark="调用助手模型的url"),
            # cls(key="parse_report_model_id", value="918359ff-8238-414d-8eb7-95a7dfb854a2", remark="解析文档助手模型id"),
            cls(key="parse_report_tool_id", value="7b610e8c-09e5-4813-b5da-1956b0a0e90f", remark="解析文档技能id"),
            cls(key="get_suggestion_model_id", value="20c13758-1602-46d9-b1f7-1b3a0cc52747",
                remark="获取优化建议助手模型id"),
            cls(key="use_tool_url", value="http://120.221.212.173:3001/api/v1/process/", remark="调用技能的url"),
            cls(key="suggestion_right_code_list", value="建议如下", remark="建议正确返回的code"),
            cls(key="use_suggestion_tool_id", value="fa5dbb94-cfd6-4da3-ae67-7a082109d0c5", remark="修程修制建议技能id"),
            cls(key="post_suggestion_url", value="http://ip:port/standardoperations/maintenancestrategy/publicAiSuggestion", remark="推送修程修制建议url"),
        ]

    @classmethod
    def initialize_default_configs(cls, session):
        """
        在数据库中初始化默认配置
        """
        default_configs = cls.get_default_configs()
        for config in default_configs:
            existing = session.query(cls).filter(cls.key == config.key).first()
            if not existing:
                session.add(config)
        session.commit()


class ConfigDao(MetroConfig):
    @classmethod
    def get_config(cls) -> List[MetroConfig]:
        """获取所有配置"""
        with session_getter() as session:
            statement = select(MetroConfig)
            return session.exec(statement).all()

    @classmethod
    def get_config_by_id(cls, config_id: UUID) -> Optional[MetroConfig]:
        """根据ID获取特定配置"""
        with session_getter() as session:
            return session.get(MetroConfig, config_id)

    @classmethod
    def get_config_by_key(cls, key: str) -> Optional[MetroConfig]:
        """根据key获取配置"""
        with session_getter() as session:
            statement = select(MetroConfig).where(MetroConfig.key == key)
            return session.exec(statement).first()

    @classmethod
    def update_config(cls, config_id: UUID, config_data: dict) -> Optional[MetroConfig]:
        """更新配置"""
        with session_getter() as session:
            db_config = session.get(MetroConfig, config_id)
            if not db_config:
                return None
            for key, value in config_data.items():
                setattr(db_config, key, value)
            session.add(db_config)
            session.commit()
            session.refresh(db_config)
            return db_config

    @classmethod
    def delete_config(cls, config_id: UUID) -> bool:
        """删除配置"""
        with session_getter() as session:
            db_config = session.get(MetroConfig, config_id)
            if not db_config:
                return False
            session.delete(db_config)
            session.commit()
            return True

    @classmethod
    def create_config(cls, config: ConfigBase) -> Optional[MetroConfig]:
        """
        创建新的配置
        如果key已存在，则返回None表示创建失败
        """
        with session_getter() as session:
            # 检查key是否已存在
            existing_config = session.exec(select(MetroConfig).where(MetroConfig.key == config.key)).first()
            if existing_config:
                return None  # 如果key已存在，返回None

            db_config = MetroConfig.from_orm(config)
            session.add(db_config)
            session.commit()
            session.refresh(db_config)
            return db_config

    @classmethod
    def update_config_by_key(cls, key: str, config_data: dict) -> Optional[MetroConfig]:
        """
        根据key更新配置
        如果key不存在，则返回None
        """
        with session_getter() as session:
            db_config = session.exec(select(MetroConfig).where(MetroConfig.key == key)).first()
            if not db_config:
                return None
            for field, value in config_data.items():
                if hasattr(db_config, field):
                    setattr(db_config, field, value)
            session.add(db_config)
            session.commit()
            session.refresh(db_config)
            return db_config

    @classmethod
    def delete_config_by_key(cls, key: str) -> bool:
        """
        根据key删除配置
        返回True表示删除成功，False表示key不存在
        """
        with session_getter() as session:
            db_config = session.exec(select(MetroConfig).where(MetroConfig.key == key)).first()
            if not db_config:
                return False
            session.delete(db_config)
            session.commit()
            return True


class EquipmentBase(SQLModelSerializable):
    id: UUID = Field(nullable=False, primary_key=True, description='唯一ID')
    spinyinsimple: str = Field(index=False, default='', description='设备简拼')
    spininfull: str = Field(index=False, default='', description='设备全拼')
    sfname: str = Field(index=False, default='', description='设备名称')
    sfcode: str = Field(index=False, default='', description='设备编号')
    isfstate: str = Field(index=False, default='', description='设备状态')
    isflogo: str = Field(index=False, default='', description='设备标识')
    srfcard: str = Field(index=False, default='', description='射频卡号')
    sinstallpos: str = Field(index=False, default='', description='安装位置')
    isfimport: str = Field(index=False, default='', description='是否进口')
    snote: str = Field(index=False, default='', description='设备说明')
    igrade: str = Field(index=False, default='', description='设备等级')
    iclassid: str = Field(index=False, default='', description='设备分类')
    imajorid: str = Field(index=False, default='', description='设备专业')
    sfname_as: str = Field(index=False, default='', description='设备别名')
    sdevicetype: str = Field(index=False, default='', description='设备类型')
    ilevel: str = Field(index=False, default='', description='设备层级')
    create_time: Optional[datetime] = Field(
        sa_column=Column(DateTime, nullable=False, server_default=text('CURRENT_TIMESTAMP')))
    update_time: Optional[datetime] = Field(
        sa_column=Column(DateTime,
                         nullable=False,
                         index=False,
                         server_default=text('CURRENT_TIMESTAMP'),
                         onupdate=text('CURRENT_TIMESTAMP')))


class Equipment(EquipmentBase, table=True):
    id: UUID = Field(default_factory=uuid4, primary_key=True, unique=True)


class EquipmentDao(Equipment):
    @classmethod
    def bulk_insert(cls, equipments: List[Equipment]):
        with session_getter() as session:
            session.add_all(equipments)
            session.commit()

    @classmethod
    def delete_all(cls):
        with session_getter() as session:
            session.query(Equipment).delete()
            session.commit()

    @classmethod
    def get_by_sfcode(cls, sfcode: str) -> Optional[Equipment]:
        with session_getter() as session:
            statement = select(Equipment).where(Equipment.sfcode == sfcode)
            return session.exec(statement).first()
